/**
 * axios http
 */
import Axios from 'axios'
import qs from 'qs'
import _ from 'lodash'
import { Message } from 'element-ui'

/** axios默认配置 */
let configAxios = {
	// baseURL: '无需配置，由vue自动代理, 见vue.config.js->devServer.proxy'
	// baseURL: '/api',
	// Timeout
	timeout: 60 * 1000,
	withCredentials: true
}

/** 会话票据请求头名称 */
const HEADER_TOKEN_NAME = 'DDR-TICKET'
/** 会话票据请求头名称 */
const TOKEN_NAME = 'token'
/** 登录页面 */
// const LOGIN_PAGE = '/login'
/** ajax请求工具实例 */
const axios = Axios.create(configAxios)

/** axios请求拦截器 */
axios.interceptors.request.use(
	(config) => {
		let token = sessionStorage.getItem(TOKEN_NAME)
		if (_.isString(token)) {
			config.headers[HEADER_TOKEN_NAME] = token
		}
		return config
	},
	(error) => {
		Promise.reject(error)
	}
)

/** axios响应拦截器 */
axios.interceptors.response.use(
	(response) => {
		return successCallback(response)
	},
	(error) => {
		// Do something with response error
		return errorCallback(error)
	}
)

/**
 * 错误回调函数
 * @param {*} error 错误对象
 */
const errorCallback = (error) => {
	if (error.response) {
		// The request was made and the server responded with a status code
		// that falls out of the range of 2xx
		if (error.response.data.status) {
			// // 未登录
			// if (error.response.data.status === 30001) {
			//   // sessionStorage.clear()
			//   window.location.href = error.response.data.data
			// } else {
			Message({
				message: error.response.data.message,
				type: 'error'
			})
			// }
		} else {
			Message({
				// 服务挂了
				message: '当前服务异常或网络异常, 请稍后再试',
				type: 'error'
			})
		}
	} else if (error.request) {
		// The request was made but no response was received
		// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
		// http.ClientRequest in node.js
		Message({
			// 网络挂了或服务忙（超时未收到响应）
			message: '当前服务忙或网络异常, 请稍后再试',
			type: 'error'
		})
	} else {
		// Something happened in setting up the request that triggered an Error
		Message({
			message: error.message,
			type: 'error'
		})
	}
	return Promise.reject(error)
}

/**
 * 成功回调函数
 * @param {*} response 响应对象
 */
const successCallback = (response) => {
	if (response.status > 200) {
		return response.data
	}
	if (response.data.status === 0) {
		return response.data
	}
	// if (response.data.status === 2) { // 未授权code
	//   // 由服务端控制的在ajax中进行的redirect跳转，data属性即为跳转的URL
	//   window.location.href = LOGIN_PAGE
	//   return
	// }
	if (response.data.message) {
		Message({
			message: response.data.message,
			type: 'error'
		})
	}
	return Promise.reject(response.data)
}

/**
 * get
 * @param {String} apiUri api uri
 * @param {Object} params 参数
 */
const get = (apiUri, params) => {
	return axios.get(apiUri, params)
}

/**
 * post
 * @param {String} apiUri api uri
 * @param {ObjectOrJsonString} params 请求参数，对象或json字符串
 * @return {Promise} Promise
 */
const post = (apiUri, params) => {
	let _param = _.isString(params) ? params : qs.stringify(params)
	return axios.post(apiUri, _param, {
		headers: {
			'Content-Type': 'application/x-www-form-urlencoded'
		}
	})
}
const postJson = (apiUri, params) => {
	// let _param = _.isString(params) ? params : qs.stringify(params)
	return axios.post(apiUri, JSON.stringify(params), {
		headers: {
			'Content-Type': 'application/json;charset=UTF-8'
		}
	})
}

/**
 * 下载文件
 * 业务代码中的使用示例：
 * this.$http.download('/common/versionUpdate/download', 'filename.pdf', { aa: 'aaasdf', bb: 1 })
 * @param {String} uri 下载地址
 * @param {String} filename 文件名称
 * @param {Object} params 请求参数
 */
const download = (uri, filename, params) => {
	let userAgent = navigator.userAgent.toLowerCase()
	if (userAgent.indexOf('chrome') > -1 || userAgent.indexOf('firefox') > -1) {
		// chrome,firefox
		console.log('downloadGet in chrome')
		downloadSafe(uri, filename, params)
	} else {
		// IE11,...
		console.log('downloadGet in ie')
		downloadGet(uri, params)
	}
}

/**
 * 下载文件，不安全，get方式，无安全标签和token, 文件名称由服务端响应头控制
 * chrome, 360极速, IE11: down OK
 * firefox down failure
 * @param {String} uri 下载地址
 * @param {Object} params 请求参数
 */
const downloadGet = (uri, params) => {
	console.log('downloadGet in')
	return new Promise((resolve, reject) => {
		try {
			console.log('Promise in 1')
			let iframe = document.createElement('iframe')
			iframe.style.display = 'none'
			// iframe.id = 'NJA_FRAME_ID';
			let ps = param2String(params)
			if (uri.indexOf('?') !== -1) {
				uri += '&' + ps
			} else {
				if (ps.indexOf('=') !== -1) {
					uri += '?' + ps
				}
			}
			console.log('Promise in 2', uri)
			iframe.onload = function () {
				// TODO 这下载不调用问题
				console.log('Promise in 3', uri)
				document.body.removeChild(iframe)
			}
			console.log('Promise in 4', uri)
			if (uri.indexOf('http') !== 0) {
				iframe.src = uri
				// iframe.src = 'http://localhost:' + vueConfig.devServer.port + '/api' + uri
				console.log('Promise in 4 1', uri)
				// iframe.src = store.getters.serviceHost + uri
			} else {
				iframe.src = uri
				console.log('Promise in 4 2', uri)
			}
			console.log('Promise in 5', uri)
			setTimeout(() => {
				resolve('ok')
			}, 1000)
			console.log('Promise in 6', uri)
			window.addEventListener('message', function (error) {
				let res = JSON.parse(error.data)
				if (
					res &&
					typeof res === 'object' &&
					'code' in res &&
					res.code !== 20000
				) {
					reject(res)
				}
			})
			document.body.appendChild(iframe)
		} catch (e) {}
	})
}

/**
 * 将get请求参数转为字符串
 * 示例：{a: 'aa', b: 123} => a=aa&b=123
 * @param {Object/String} params get请求参数
 * @returns {String} 参数字符串
 */
const param2String = (params) => {
	if (typeof params === 'string') {
		return params
	}
	let ret = ''
	for (let it in params) {
		let val = params[it]
		if (
			typeof val === 'object' && //
			(!(val instanceof Array) ||
				(val.length > 0 && typeof val[0] === 'object'))
		) {
			val = JSON.stringify(val)
		}
		ret += it + '=' + encodeURIComponent(val) + '&'
	}
	if (ret.length > 0) {
		ret = ret.substring(0, ret.length - 1)
	}
	return ret
}

/**
 * 安全下载，post with token
 * firefox down OK need filename
 * chrome down OK need filename
 * 360极速(blink内核) down OK need filename
 * IE11 down failure
 * @param {String} uri 下载地址
 * @param {String} filename 文件名称
 * @param {Object} params 请求参数
 */
const downloadSafe = (uri, filename, params) => {
	axios({
		method: 'post',
		url: uri,
		data: qs.stringify(params),
		// 指定返回服务器返回的数据类型
		responseType: 'blob'
	})
		.then((response) => {
			// 处理返回的文件流
			let blob = response
			let reader = new FileReader()
			// 转换为base64，可以直接放入a标签href
			reader.readAsDataURL(blob)
			reader.onload = function (e) {
				let link = document.createElement('a')
				link.download = filename
				link.href = e.target.result
				document.body.appendChild(link)
				link.click()
				// 释放URL对象
				window.URL.revokeObjectURL(link.href)
				// 删除link对象
				document.body.removeChild(link)
			}
		})
		.catch((err) => {
			Message({
				message: '文件下载失败: ' + err,
				type: 'error'
			})
		})
}

// 统一方法输出口
export { post, postJson, get, download, axios }
